package manager

import (
	"errors"
	"time"

	"gitcode.com/G-YT/baoyou/server/global"
	"gitcode.com/G-YT/baoyou/server/model/manager"
	"gitcode.com/G-YT/baoyou/server/model/user"
	"gitcode.com/G-YT/baoyou/server/utils"
	"gorm.io/gorm"
)

type TargetPlanService struct{}

func (targetPlanService *TargetPlanService) SaveTargetPlan(tp *manager.TargetPlan) error {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		var existing manager.TargetPlan
		err := tx.Where("hm_id = ?", tp.HmID).First(&existing).Error
		if errors.Is(err, gorm.ErrRecordNotFound) {
			if err = tx.Create(tp).Error; err != nil {
				return err
			}
		} else if err != nil {
			return err
		}
		// 归一化到东八区的自然日：开始->当天00:00，结束->当天23:59:59.999
		proStart := utils.DateStartCST(tp.ProBonoStartTime)
		proEnd := utils.DateEndCST(tp.ProBonoEndTime)
		incrStart := utils.DateStartCST(tp.IncrVipStartTime)
		incrEnd := utils.DateEndCST(tp.IncrVipEndTime)
		servStart := utils.DateStartCST(tp.ServiceVipStartTime)
		servEnd := utils.DateEndCST(tp.ServiceVipEndTime)
		now := time.Now().In(utils.Shanghai())
		proStatus := targetPlanService.statusByRange(now, proStart, proEnd, tp.ProBonoNum)
		incrStatus := targetPlanService.statusByRange(now, incrStart, incrEnd, tp.IncrVipNum)
		servStatus := targetPlanService.statusByRange(now, servStart, servEnd, tp.ServiceVipNum)
		updates := map[string]interface{}{
			"pro_bono_num":           tp.ProBonoNum,
			"pro_bono_start_time":    proStart,
			"pro_bono_end_time":      proEnd,
			"incr_vip_num":           tp.IncrVipNum,
			"incr_vip_start_time":    incrStart,
			"incr_vip_end_time":      incrEnd,
			"service_vip_num":        tp.ServiceVipNum,
			"service_vip_start_time": servStart,
			"service_vip_end_time":   servEnd,
			"pro_bono_status":        proStatus,
			"incr_vip_status":        incrStatus,
			"service_vip_status":     servStatus,
		}
		return tx.Model(&manager.TargetPlan{}).Where("hm_id = ?", tp.HmID).Updates(updates).Error
	})
}

func (targetPlanService *TargetPlanService) GetTargetPlan(hmID uint) (manager.TargetPlan, error) {
	var tp manager.TargetPlan
	if err := global.GVA_DB.Where("hm_id = ?", hmID).First(&tp).Error; err != nil {
		return tp, err
	}
	if !tp.ProBonoStartTime.IsZero() && !tp.ProBonoEndTime.IsZero() && !tp.ProBonoEndTime.Before(tp.ProBonoStartTime) {
		var n int64
		_ = global.GVA_DB.Model(&user.User{}).
			Where("health_manager_id = ? AND created_at BETWEEN ? AND ?", hmID, tp.ProBonoStartTime, tp.ProBonoEndTime).
			Count(&n).Error
		tp.ProBonoCurrentNum = uint(n)
	} else {
		tp.ProBonoCurrentNum = 0
	}
	if !tp.IncrVipStartTime.IsZero() && !tp.IncrVipEndTime.IsZero() && !tp.IncrVipEndTime.Before(tp.IncrVipStartTime) {
		var n int64
		_ = global.GVA_DB.Model(&user.User{}).
			Where("health_manager_id = ? AND types = 2 AND created_at BETWEEN ? AND ?", hmID, tp.IncrVipStartTime, tp.IncrVipEndTime).
			Count(&n).Error
		tp.IncrVipCurrentNum = uint(n)
	} else {
		tp.IncrVipCurrentNum = 0
	}
	if !tp.ServiceVipStartTime.IsZero() && !tp.ServiceVipEndTime.IsZero() && !tp.ServiceVipEndTime.Before(tp.ServiceVipStartTime) {
		var n int64
		_ = global.GVA_DB.Model(&manager.MessageNotice{}).
			Where("hm_id = ? AND created_at BETWEEN ? AND ?", hmID, tp.ServiceVipStartTime, tp.ServiceVipEndTime).
			Count(&n).Error
		tp.ServiceVipCurrentNum = uint(n)
	} else {
		tp.ServiceVipCurrentNum = 0
	}
	return tp, nil
}

// statusByRange 用于根据当前时间与目标的起止时间以及目标人数，判断目标的状态
// 返回值约定：
// 0 = 未创建：未设置起止时间或目标人数为0，或当前时间早于开始时间
// 1 = 进行中：当前时间处于 [start, end] 闭区间内，且目标人数>0
// 2 = 已结束：当前时间晚于结束时间
func (targetPlanService *TargetPlanService) statusByRange(now, start, end time.Time, target uint) uint {
	// 未设置起止时间或未设置目标人数，视作未创建
	if start.IsZero() || end.IsZero() || target == 0 {
		return 0
	}
	// 当前时间尚未到达开始时间，仍为未创建
	if now.Before(start) {
		return 0
	}
	// 当前时间在 [start, end] 闭区间内，视为进行中
	if (now.Equal(start) || now.After(start)) && (now.Equal(end) || now.Before(end)) {
		return 1
	}
	// 当前时间晚于结束时间，视为已结束
	if now.After(end) {
		return 2
	}
	// 兜底逻辑：其它情况按未创建处理
	return 0
}
